using System;
using System.Collections.Generic;
using System.Linq;
using Fantasy.SourceGenerator.Common;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp.Syntax;

namespace Fantasy.SourceGenerator.Generators
{
    [Generator]
    public sealed class CustomRegistrarGenerator : IIncrementalGenerator
    {
        public void Initialize(IncrementalGeneratorInitializationContext context)
        {
            // 查找所有实现了 ICustomRegistrar 接口的类
            var customRegistrarTypes = context.SyntaxProvider
                .CreateSyntaxProvider(
                    predicate: static (node, _) => IsCustomRegistrar(node),
                    transform: static (ctx, _) => GetCustomRegistrar(ctx))
                .Where(static info => info != null)
                .Collect();
            // 组合编译信息和找到的类型
            var compilationAndTypes = context.CompilationProvider.Combine(customRegistrarTypes);
            // 注册源代码输出
            context.RegisterSourceOutput(compilationAndTypes, static (spc, source) =>
            {
                if (CompilationHelper.IsSourceGeneratorDisabled(source.Left))
                {
                    return;
                }
                
                if (!CompilationHelper.HasFantasyDefine(source.Left))
                {
                    return;
                }
                
                if (source.Left.GetTypeByMetadataName("Fantasy.Assembly.ICustomInterface") == null)
                {
                    return;
                }

                GenerateRegistrationCode(spc, source.Left, source.Right!);
            });
        }

        private static void GenerateRegistrationCode(
            SourceProductionContext context,
            Compilation compilation,
            IEnumerable<CustomRegistrarTypeInfo> customRegistrarTypes)
        {
            var customRegistrarTypeInfos = customRegistrarTypes.ToList();
            // 获取当前程序集名称（仅用于注释）
            var markerClassName = compilation.GetAssemblyName("CustomInterfaceRegistrar", out var assemblyName, out _);
            // 生成代码文件
            var builder = new SourceCodeBuilder();
            // 添加文件头
            builder.AppendLine(GeneratorConstants.AutoGeneratedHeader);
            // 添加 using
            builder.AddUsings(
                "System",
                "System.Collections.Generic",
                "Fantasy.Assembly",
                "Fantasy.DataStructure.Collection",
                "Fantasy.Entitas.Interface"
            );
            builder.AppendLine();
            // 开始命名空间
             builder.BeginDefaultNamespace();
            // 开始类定义（实现 ISphereEventRegistrar 接口）
            builder.AddXmlComment($"Auto-generated CustomInterface registration class for {assemblyName}");
            builder.BeginClass(markerClassName, "internal sealed", "global::Fantasy.Assembly.ICustomInterfaceRegistrar");
            // 生成注册方法
            builder.AddXmlComment("Register all CustomInterface to the containers");
            builder.BeginMethod("public void Register(global::Fantasy.DataStructure.Collection.OneToManyList<global::System.RuntimeTypeHandle, Type> customRegistrar)");
            foreach (var customRegistrarType in customRegistrarTypeInfos)
            {
                foreach (var interfaceInfo in customRegistrarType.AllInterfaces)
                {
                    builder.AppendLine($"customRegistrar.Add(typeof({interfaceInfo.FullName}).TypeHandle,typeof({customRegistrarType.TypeFullName}));");
                }
            }
            builder.EndMethod();
            builder.AppendLine();
            // 生成取消注册方法
            builder.AddXmlComment("Unregister all Event Systems from the containers (called on hot reload)");
            builder.BeginMethod("public void UnRegister(global::Fantasy.DataStructure.Collection.OneToManyList<global::System.RuntimeTypeHandle, Type> customRegistrar)");
            foreach (var customRegistrarType in customRegistrarTypeInfos)
            {
                foreach (var interfaceInfo in customRegistrarType.AllInterfaces)
                {
                    builder.AppendLine($"customRegistrar.RemoveValue(typeof({interfaceInfo.FullName}).TypeHandle,typeof({customRegistrarType.TypeFullName}));");
                }
            }
            builder.EndMethod();
            // 结束类和命名空间
            builder.EndClass();
            builder.EndNamespace();
            // 输出源代码
            context.AddSource($"{markerClassName}.g.cs", builder.ToString());
        }

        private static bool IsCustomRegistrar(SyntaxNode node)
        {
            if (node is not ClassDeclarationSyntax classDecl)
            {
                return false;
            }

            // 只要类实现了任何接口，就通过预筛选，具体检查在 GetCustomRegistrar 中进行
            if (classDecl.BaseList == null || classDecl.BaseList.Types.Count == 0)
            {
                return false;
            }

            // 快速检查：BaseList 中是否包含任何以 'I' 开头的类型（通常是接口）
            // 这是一个宽松的预筛选，真正的检查在语义分析阶段
            return true;
        }

        private static CustomRegistrarTypeInfo? GetCustomRegistrar(GeneratorSyntaxContext context)
        {
            var classDecl = (ClassDeclarationSyntax)context.Node;

            if (context.SemanticModel.GetDeclaredSymbol(classDecl) is not INamedTypeSymbol symbol)
            {
                return null;
            }

            // 跳过抽象类和接口
            if (symbol.IsAbstract || symbol.TypeKind == TypeKind.Interface)
            {
                return null;
            }
            
            var allCustomTypes = new HashSet<INamedTypeSymbol>(SymbolEqualityComparer.Default);

            try
            {
                // 1. 检查该类实现的所有接口（包括间接继承的接口）
                foreach (var iFace in symbol.AllInterfaces)
                {
                    // 排除 ICustomInterface 本身
                    if (iFace.ToDisplayString() == "Fantasy.Assembly.ICustomInterface")
                    {
                        continue;
                    }

                    // 检查该接口是否继承了 ICustomInterface（直接或间接）
                    if (iFace.AllInterfaces.Any(baseInterface =>
                            baseInterface.ToDisplayString() == "Fantasy.Assembly.ICustomInterface"))
                    {
                        allCustomTypes.Add(iFace);
                    }
                }
            
                var baseType = symbol.BaseType;
                while (baseType != null && baseType.SpecialType != SpecialType.System_Object)
                {
                    // 检查父类是否实现了 ICustomInterface 相关接口
                    var hasCustomInterface = baseType.AllInterfaces.Any(iFace =>
                        iFace.ToDisplayString() == "Fantasy.Assembly.ICustomInterface" ||
                        iFace.AllInterfaces.Any(baseInterface =>
                            baseInterface.ToDisplayString() == "Fantasy.Assembly.ICustomInterface"));

                    if (hasCustomInterface)
                    {
                        allCustomTypes.Add(baseType);
                    }

                    baseType = baseType.BaseType;
                }
            }
            catch (Exception e)
            {
                Console.WriteLine(e);
            }

            // 如果没有找到任何实现 ICustomInterface 的类型，返回 null
            if (!allCustomTypes.Any())
            {
                return null;
            }

            // 直接使用 allCustomTypes 生成接口信息列表
            var allInterfaces = allCustomTypes
                .Select(i => new InterfaceInfo(i.Name, i.GetFullName(false)))
                .ToList();

            return CustomRegistrarTypeInfo.Create(symbol, allInterfaces);
        }

        private sealed class InterfaceInfo(string name, string fullName)
        {
            public readonly string Name = name;
            public readonly string FullName = fullName;
        }

        private sealed class CustomRegistrarTypeInfo
        {
            public readonly string TypeName;
            public readonly string TypeFullName;
            public readonly string GlobalTypeFullName;
            public readonly List<InterfaceInfo> AllInterfaces;

            private CustomRegistrarTypeInfo(
                string typeName,
                string typeFullName,
                string globalTypeFullName,
                List<InterfaceInfo> allInterfaces)
            {
                TypeName = typeName;
                TypeFullName = typeFullName;
                GlobalTypeFullName = globalTypeFullName;
                AllInterfaces = allInterfaces;
            }

            public static CustomRegistrarTypeInfo Create(INamedTypeSymbol symbol, List<InterfaceInfo> allInterfaces)
            {
                return new CustomRegistrarTypeInfo(
                    symbol.Name,
                    symbol.GetFullName(false),
                    symbol.GetFullName(),
                    allInterfaces);
            }
        }
    }
}